--================================================================================================================
-- 添加mod专属水上建造模式,原版的水上建造模式,岸边无法放置
--================================================================================================================
AddSimPostInit(function()
    local _CanDeployRecipeAtPoint = Map.CanDeployRecipeAtPoint
    function Map:CanDeployRecipeAtPoint(pt, recipe, rot, ...)
        local is_valid_ground = false
        if recipe.build_mode == "BBOY_WATER" then
            local pt_x, pt_y, pt_z = pt:Get()
            is_valid_ground = not self:IsPassableAtPoint(pt_x, pt_y, pt_z)
            if is_valid_ground then
                is_valid_ground = self:IsSurroundedByWater(pt_x, pt_y, pt_z, 0)
            end
            return is_valid_ground
                and (recipe.testfn == nil or recipe.testfn(pt, rot))
                and self:IsDeployPointClear(pt, nil, recipe.min_spacing or 3.2)
        end
        return _CanDeployRecipeAtPoint(self, pt, recipe, rot, ...)
    end
end)

--================================================================================================================
-- hook所有prefab,让生物掉落中元节包裹(已弃用)
--================================================================================================================
-- AddPrefabPostInitAny(function(inst)
--     if not TheWorld.ismastersim then
--         return inst
--     end
--     if (not inst:HasTag("player")) and (not inst:HasTag("wall")) and inst.components.health ~= nil then
--         if inst.components.lootdropper then
--             if inst.components.health.maxhealth >= 10 and inst.components.health.maxhealth <= 150 and TUNING.BBOY.LOST_PACKAGE == "NO" then
--                 inst.components.lootdropper:AddChanceLoot("bboy_lost_package", 0.05)
--             elseif inst.components.health.maxhealth > 150 and inst.components.health.maxhealth < 2500 and TUNING.BBOY.LOST_PACKAGE == "NO" then
--                 inst.components.lootdropper:AddChanceLoot("bboy_lost_package", 0.3)
--             elseif inst.components.health.maxhealth >= 2500 then
--                 inst.components.lootdropper:AddChanceLoot("bboy_lost_package", 1)
--                 inst.components.lootdropper:AddChanceLoot("bboy_lost_package", 0.3)
--                 inst.components.lootdropper:AddChanceLoot("bboy_lost_package", 0.3)
--             end
--         end
--     end
-- end)

--================================================================================================================
-- 玩家携带彼岸蛾会得到 6.25/min 的升san光环(写的不一定完美)
--================================================================================================================
local function HasNetherMothInInventoryFor_Checker(item)
    return item:HasTag("bboy_nether_moth")
end

-- 该函数参考了"玩家身上是否携带肉"的代码
local function HasNetherMothInInventoryFor(inst)
    local inventory = inst.components.inventory
    if inventory == nil then
        return false
    end
    return inventory:FindItem(HasNetherMothInInventoryFor_Checker) ~= nil
end

local function AddSanityDrainAura(inst)
    if inst.components.sanity == nil then
        return
    end

    local function CheckNetherMoth(inst, data)
        -- 判断得到失去的物品是否是彼岸蛾，若不是就跳过(减少性能损耗。。也许吧)
        local prefab_name = nil
        if data.item ~= nil then
            prefab_name = data.item.prefab
        elseif data.prev_item ~= nil then
            prefab_name = data.prev_item.prefab
        end
        if prefab_name ~= "bboy_nether_moth" then
            return
        end

        -- 判断身上是否还有彼岸蛾
        local has_nether_moth = false
        has_nether_moth = HasNetherMothInInventoryFor(inst)

        if has_nether_moth then
            inst.components.sanity.externalmodifiers:SetModifier("sanity_drain_bboy", 5 / 48, "bboy_nether_moth")
        else
            inst.components.sanity.externalmodifiers:RemoveModifier("sanity_drain_bboy", "bboy_nether_moth")
        end
    end

    -- 监听物品栏得到，失去物品
    inst:ListenForEvent("itemget", CheckNetherMoth)
    inst:ListenForEvent("itemlose", CheckNetherMoth)
end

AddPlayerPostInit(function(inst)
    if not TheWorld.ismastersim then
        return
    end
    AddSanityDrainAura(inst)
end)

--================================================================================================================
-- 放置枯井会弹出书写界面
--================================================================================================================
local writeables = require "writeables"
local SignGenerator = require "signgenerator"
local kinds = {}
kinds["bboy_dry_well"] = { -- 枯井
    prompt = STRINGS.SIGNS.MENU.PROMPT,
    animbank = "ui_board_5x3",
    animbuild = "ui_board_5x3",
    menuoffset = Vector3(6, -70, 0),

    cancelbtn = { text = STRINGS.SIGNS.MENU.CANCEL, cb = nil, control = CONTROL_CANCEL },
    middlebtn = {
        text = STRINGS.SIGNS.MENU.RANDOM,
        cb = function(inst, doer, widget)
            widget:OverrideText(SignGenerator(inst, doer))
        end,
        control = CONTROL_MENU_MISC_2
    },
    acceptbtn = { text = STRINGS.SIGNS.MENU.ACCEPT, cb = nil, control = CONTROL_ACCEPT },
}

local writeables_makescreen = writeables.makescreen
local writeables_GetLayout = writeables.GetLayout

function writeables.makescreen(inst, doer)
    local data = kinds[inst.prefab]
    if data then
        if doer and doer.HUD then
            return doer.HUD:ShowWriteableWidget(inst, data)
        end
    else
        return writeables_makescreen(inst, doer)
    end
end

function writeables.GetLayout(name)
    if name and kinds[name] then
        return kinds[name]
    else
        return writeables_GetLayout(name)
    end
end

--================================================================================================================
-- 幽冥雾中玩家不会触发群体仇恨
--================================================================================================================
AddComponentPostInit("combat", function(self)
    local OldShareTarget = self.ShareTarget
    self.ShareTarget = function(self, target, range, fn, maxnum, musttags, ...)
        if target and target:HasTag("notarget") then
            return
        end
        if OldShareTarget then
            OldShareTarget(self, target, range, fn, maxnum, musttags, ...)
        end
    end
end)

--================================================================================================================
-- 幽冥雾中玩家屏幕会有云雾飘动&&玩家被攻击,纸人仆从会放下工作协助玩家战斗
--================================================================================================================
local function SetNightBerryCakeVision(inst)
    if inst.components.playervision then
        if inst.bboycloudsover and inst.bboycloudsover:value() then
            if inst.HUD then
                inst.HUD:ShowBboyClouds(0.5)
            end
        else
            if inst.HUD then
                inst.HUD:HideBboyClouds()
            end
        end
    end
end

local function OnLeaderAttacked(inst, data)
    local attacker = data.attacker
    if attacker ~= nil and attacker:IsValid() and attacker.components.health ~= nil and not attacker.components.health:IsDead() then
        for pet, _ in pairs(inst.components.leader.followers) do
            if pet.prefab == "bboy_paper_effigy" and pet.components.combat ~= nil then
                pet.components.combat:SuggestTarget(attacker)
            end
        end
    end
end

AddPlayerPostInit(function(inst)
    inst.bboycloudsover = GLOBAL.net_bool(inst.GUID, "bboycloudsover", "bboycloudsoverdirty")
    inst:ListenForEvent("bboycloudsoverdirty", SetNightBerryCakeVision)

    -- 服务器端
    if TheWorld.ismastersim then
        inst:ListenForEvent("attacked", OnLeaderAttacked)
    end
end)

--================================================================================================================
-- 给世界添加嗨猪管理组件
--================================================================================================================
AddPrefabPostInit("world", function(inst)
    if not TheWorld.ismastersim then
        return
    end
    if not inst.components.timer then
        inst:AddComponent("timer")
    end
    inst:AddComponent("bboy_piggyhimanager")
end)

--================================================================================================================
-- 给流浪商人添加自己mod的货物
--================================================================================================================
AddPrefabPostInit("wanderingtrader", function(inst)
    -- 只在主世界执行
    if not TheWorld.ismastersim then
        return
    end

    -- 初始化自定义货物表
    if inst.WARES == nil then
        inst.WARES = {}
    end

    -- 如果表不存在，就创建
    if inst.WARES.BBOY == nil then
        inst.WARES.BBOY = {
            {
                ["bboy_fireworks"] = {
                    recipe = "wanderingtradershop_bboy_fireworks",
                    min = 1,
                    max = 2,
                    limit = 2,
                },
            },
        }
    end

    -- Hook 原本的 RerollWares 函数
    local _OldRerollWares = inst.RerollWares

    inst.RerollWares = function(inst)
        -- 先执行原逻辑
        if _OldRerollWares ~= nil then
            _OldRerollWares(inst)
        end

        -- 再追加自定义货物
        if inst.WARES and inst.WARES.BBOY then
            for i = 1, #inst.WARES.BBOY do
                inst:AddWares(inst.WARES.BBOY[i])
            end
        end
    end

    -- 第三步：立即刷新一次
    inst:DoTaskInTime(1, function()
        inst:RerollWares()
    end)
end)
